/*************************************************************
*	Writes data from input into the given file 
*************************************************************/

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.LinkedList;


public class WriteFilter extends InstrumentationFilterFramework{

	//final output files
	private static File outputFile;
	int count =0;

	//lists to hold data before written to file
	final private LinkedList<Long> times = new LinkedList<Long>();
	final private LinkedList<Double> alts = new LinkedList<Double>();
	final private LinkedList<Double> psi = new LinkedList<Double>();
	final private LinkedList<Double> temps = new LinkedList<Double>();
	final private LinkedList<Double> pitch = new LinkedList<Double>();

	//Formatting section
	//CHANGE: Originally, the date format was "yyyy MM dd::hh:mm:ss:SSS"
	final private SimpleDateFormat TimeStampFormat = new SimpleDateFormat("yyyy:DD:HH:mm:ss");
	final private DecimalFormat tempFormat = new DecimalFormat("000.00000");
	final private DecimalFormat psiFormat = new DecimalFormat("00.00000");
	final private DecimalFormat altFormat = new DecimalFormat("000000.00000");
	//end of formatting

	WriteFilter(String file){
		outputFile = new File(file);
	}
	
	public void run()
	{

		Calendar TimeStamp = Calendar.getInstance();


		int MeasurementLength = 8;		// This is the length of all measurements (including time) in bytes
		int IdLength = 4;				// This is the length of IDs in the byte stream

		byte databyte = 0;				// This is the data byte read from the stream
		int bytesread = 0;				// This is the number of bytes read from the stream

		long measurement;				// This is the word used to store all measurements - conversions are illustrated.
		int id;							// This is the measurement id
		int i;							// This is a loop counter

		/*************************************************************
		 *	First we announce to the world that we are alive...
		 **************************************************************/

		System.out.print( "\n" + this.getName() + "::Writer Reading, writing to file: "+ outputFile);


		try {
			outputFile.delete();
			FileWriter writer = new FileWriter(outputFile);
			outputFile.createNewFile();
			writer.write("Time: \t\t\tTemperature (C):\tPressure (PSI):\tAltitude (m):\tPitch (degrees):\n");
			while (true)
			{
				try
				{

					/*************************************************************
					 *	Read id
					 **************************************************************/

					id = 0;

					for (i=0; i<IdLength; i++ )
					{
						databyte = ReadFilterInputPort();	// This is where we read the byte from the stream...

						id = id | (databyte & 0xFF);		// We append the byte on to ID...

						if (i != IdLength-1)				// If this is not the last byte, then slide the
						{									// previously appended byte to the left by one byte
							id = id << 8;					// to make room for the next byte we append to the ID

						} // if

						bytesread++;						// Increment the byte count

					} // for

					measurement = 0;

					/*************************************************************
					 *	Read measurements
					 **************************************************************/
					
					for (i=0; i<MeasurementLength; i++ )
					{
						databyte = ReadFilterInputPort();
						measurement = measurement | (databyte & 0xFF);	// We append the byte on to measurement...

						if (i != MeasurementLength-1)					// If this is not the last byte, then slide the
						{												// previously appended byte to the left by one byte
							measurement = measurement << 8;				// to make room for the next byte we append to the
							// measurement
						} // if

						bytesread++;									// Increment the byte count

					} // if

					/*************************************************************
					 *	Classify the measurement
					 **************************************************************/
					
					if ( id ==  Measurement.TIME.getID())
					{
						//adds the time measurement

						times.add(measurement);

						count++;
					} // if

					else if ( id == Measurement.ALTITUDE.getID() )
					{	
						//convert to double
						double altMeters = Double.longBitsToDouble(measurement);

						//adds the altitude measurement
						alts.add(altMeters);


					} // if

					else if ( id == Measurement.PRESSURE.getID() )
					{	
						//convert to double
						double pressure = Double.longBitsToDouble(measurement);

						//adds the pressure measurement
						psi.add(pressure);


					} // if

					else if ( id == Measurement.TEMPERATURE.getID() )
					{
						//CHANGE: converts Fahrenheit to Celsius and passes value

						//convert to celsius
						double celsius = (Double.longBitsToDouble(measurement));

						//adds the temperature measurement
						temps.add(celsius);

					} // if
					else if ( id == Measurement.PITCH.getID() )
					{
						//CHANGE: converts Fahrenheit to Celsius and passes value

						//convert to celsius
						double pit = (Double.longBitsToDouble(measurement));

						//adds the temperature measurement
						pitch.add(pit);

					} // if

					/*************************************************************
					 *	If there is a full frame of data, write to output file
					 **************************************************************/
					if(
							times.size() > 0 &&
							temps.size() > 0 &&
							psi.size()   > 0 &&
							alts.size()  > 0 &&
							pitch.size() > 0
					){
						TimeStamp.setTimeInMillis(times.removeFirst());
						writer.write("\n"+
								TimeStampFormat.format(TimeStamp.getTime()) +"\t\t" +
								tempFormat.format(temps.removeFirst()) + "\t\t" +
								psiFormat.format(psi.removeFirst()) + "\t\t"+
								altFormat.format(alts.removeFirst()) +"\t"+
								pitch.removeFirst()
						);
						writer.flush();
					}

				} // try

				/*******************************************************************************
				 *	Close down upon EndOfStreamException
				 ********************************************************************************/

				catch (EndOfStreamException e)
				{
					writer.close();
					ClosePorts();
					System.out.print( "\n" + this.getName() + "::Writer Exiting; bytes read: " + bytesread +"; "+count + " frames of data written\n");
					break;

				} // catch
				catch (IOException e) {
					e.printStackTrace();
				}

			} // while

		}catch(IOException e){
			e.printStackTrace();
		}
	}
}
